home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Commun⁄Network / RevRdist Folder / RevRdist / RevRdist src / desktop.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-05  |  12.5 KB  |  523 lines  |  [TEXT/KAHL]

  1. /*
  2.  * desktop.c - functions related to desktop database
  3.  */
  4.  
  5. #include "RevRdist.h"
  6. #include <Finder.h>
  7. #include "desktop.h"
  8.  
  9. static    Handle    APPLh;                    /* handle to APPL resource */
  10. static    Integer    Deskrefnum;                /* refnum for desktop file */
  11. static    Integer    ClientDTRef;            /* refnum for client desktop data base */
  12. static    Integer    ServerDTRef;            /* refnum for server desktop data base */
  13.  
  14. /*
  15.  * Structure of application info in Desktop file
  16.  */
  17. struct    applinfo
  18. {
  19.     OSType                creator;        /* creator/owner id */
  20.     Longint                dirID;            /* directory containing appl */
  21. /*    char                applname[0];    /* file name */
  22. };
  23. typedef    struct applinfo    api_t;
  24.  
  25. void modify_dtfile (cnode_t *, Boolean);
  26.  
  27.  
  28.  
  29. /*
  30.  *=========================================================================
  31.  * desktop_end() - release access to desktop files, etc
  32.  *=========================================================================
  33.  */
  34. void
  35. desktop_end(void)
  36. {
  37.     if (APPLh)
  38.     {
  39.         ReleaseResource(APPLh);
  40.         APPLh = nil;
  41.     }
  42.     if (Deskrefnum)
  43.         CloseResFile (Deskrefnum);
  44.     Deskrefnum = 0;
  45.     ClientDTRef = 0;
  46.     ServerDTRef = 0;
  47. }
  48.  
  49.  
  50. /*
  51.  *=========================================================================
  52.  * desktop_remove(cip, cp) - remove info for file from desktop
  53.  * entry:    cp = ptr to cnode for file to remove
  54.  *            desktop_start() called
  55.  * exit:    information about file removed from desktop database
  56.  *=========================================================================
  57.  */
  58. void
  59. desktop_remove(cnode_t *cp)
  60. {
  61.     OSErr            error;
  62.     DTPBRec            cdtpb;                /* client desktop parameter block */
  63.     int                didit;
  64.  
  65.     Clue0 = "\pdesktop_remove";
  66.     if (ClientDTRef)
  67.     {
  68.         didit = 0;
  69.         if (Flags & PF_LISTONLY)
  70.             return;
  71.         ZERO(cdtpb);
  72.         cdtpb.ioDTRefNum = ClientDTRef;
  73.         cdtpb.ioNamePtr = cp->name;
  74.         cdtpb.ioDirID = cp->parID;
  75.         error = PBDTRemoveComment(&cdtpb, false);
  76.         if (error && error != afpItemNotFound && error != fnfErr)
  77.         {
  78.             ClueID = error;
  79.             warning (E_SYS, Clue1, "\pPBDTRemoveComment", nil);
  80.         }
  81.         if (error == 0)
  82.             didit = 1;
  83.         if (cp->in.f.finfo.fdType == 'APPL' && (cp->in.f.finfo.fdFlags & fHasBundle))
  84.         {
  85.             cdtpb.ioTagInfo = 0;
  86.             cdtpb.ioFileCreator = cp->in.f.finfo.fdCreator;
  87.             error = PBDTRemoveAPPL(&cdtpb, false);
  88.             if (error && error != afpItemNotFound && error != fnfErr)
  89.             {
  90.                 ClueID = error;
  91.                 warning (E_SYS, Clue1, "\pPBDTRemoveAPPL", nil);
  92.             }
  93.             if (error == 0)
  94.                 didit = 1;
  95.         }
  96.         if (didit && (Flags & PF_VERBOSE))
  97.             notice (L_DTDEL, cp->name, nil);
  98.         return;
  99.     }
  100.     /*
  101.      * Here if old style Desktop file
  102.      */
  103.     modify_dtfile (cp, false);
  104. }
  105.  
  106.  
  107.  
  108. /*
  109.  *=========================================================================
  110.  * desktop_start() - get access to desktop files, etc
  111.  * entry:    ClientVol, ServerVol set
  112.  *            ClientVIB, ServerVIB set
  113.  * returns:    OSErr if cannot open database
  114.  *=========================================================================
  115.  */
  116. OSErr
  117. desktop_start(void)
  118. {
  119.     OSErr                error;
  120.     Integer                cur;            /* saved current resource file */
  121.     Handle                hdl;            /* temp handle to APPL resource */
  122.     DTPBRec                dtpb;            /* desktop database info */
  123.     HParamBlockRec        hpb;            /* for GetVInfo, etc calls */
  124.     GetVolParmsInfoBuffer vib;            /* for GetVolParms */
  125.     Str255                s;                /* string temp */
  126.  
  127.     Clue0 = "\pdesktop_start";
  128.     ClientDTRef = 0;
  129.     ServerDTRef = 0;
  130.     if (ServerVIB.vMAttrib & (1<<bHasDesktopMgr))
  131.     {
  132.         ZERO (dtpb);
  133.         dtpb.ioVRefNum = ServerVol;
  134.         error = PBDTGetPath(&dtpb);
  135.         if (error)
  136.         {
  137.             ClueID = error;
  138.             warning (E_SYS, Clue0, "\pPBDTGetPath", nil);
  139.         } else {
  140.             ServerDTRef = dtpb.ioDTRefNum;
  141.         }
  142.     }
  143.     if (ClientVIB.vMAttrib & (1<<bHasDesktopMgr))
  144.     {
  145.         ZERO (dtpb);
  146.         dtpb.ioVRefNum = ClientVol;
  147.         error = PBDTGetPath(&dtpb);
  148.         if (error)
  149.         {
  150.             ClueID = error;
  151.             warning (E_SYS, Clue0, "\pPBDTGetPath", nil);
  152.         } else {
  153.             ClientDTRef = dtpb.ioDTRefNum;
  154.         }
  155.     }
  156.     if (ClientDTRef == 0)
  157.     {
  158.         /*
  159.          * No Desktop database, use old style Desktop file and get APPL resource
  160.          */
  161.         hdl = GetResource ('APPL', 0);    /* see if available already (debugging) */
  162.         if (hdl == 0)
  163.         {
  164.             /*
  165.              * Try to open Finder's Desktop file to find resource
  166.              */
  167.             cur = CurResFile();
  168.             Deskrefnum = OpenRFPerm("\pDesktop", ClientVol, fsRdWrPerm);
  169.             if (Deskrefnum == -1)
  170.                 Deskrefnum = 0;                /* could not open desktop */
  171.             else
  172.                 hdl = GetResource ('APPL', 0);
  173.             UseResFile(cur);
  174.         }
  175.         if (hdl == 0)
  176.         {
  177.             if (Deskrefnum)
  178.             {
  179.                 CloseResFile (Deskrefnum);
  180.                 Deskrefnum = 0;
  181.             }
  182.         }
  183.         APPLh = hdl;
  184.     }
  185.     return 0;
  186. }
  187.  
  188.  
  189.  
  190. /*
  191.  *=========================================================================
  192.  * desktop_update(sp, cp) - add/update info for file in desktop databases
  193.  * entry:    sp = ptr to cnode for server file cp is a copy of
  194.  *            cp = ptr to cnode for client file
  195.  *            desktop_start() called
  196.  * exit:    information about file added to or updated in desktop database
  197.  *=========================================================================
  198.  */
  199. void
  200. desktop_update (cnode_t *sp, cnode_t *cp)
  201. {
  202.     OSErr            error;
  203.     int                i, j;                /* temp index */
  204.     int                modified;            /* non-zero if database updated */
  205.     int                once = 0;            /* used to issue messages only once */
  206.     int                t;                    /* temp */
  207.     DTPBRec            cdtpb;                /* client desktop parameter block */
  208.     DTPBRec            sdtpb;                /* server desktop parameter block */
  209.     char            buf[1024];            /* buffer for icons or comments */
  210. static struct                            /* icon information */
  211.     {
  212.         int        itype;
  213.         int        isize;
  214.     } ii[] =
  215.     {    {kLargeIcon, kLargeIconSize}
  216.     ,    {kLarge4BitIcon, kLarge4BitIconSize}
  217.     ,    {kLarge8BitIcon, kLarge8BitIconSize}
  218.     ,    {kSmallIcon, kSmallIconSize}
  219.     ,    {kSmall4BitIcon, kSmall4BitIconSize}
  220.     ,    {kSmall8BitIcon, kSmall8BitIconSize}
  221.     };
  222.  
  223.     Clue0 = "\pdesktop_update";
  224.     modified = 0;
  225.     /*
  226.      * Always update comment information, when available
  227.      */
  228.     if (ClientDTRef && ServerDTRef)
  229.     {
  230.         ZERO (sdtpb);
  231.         sdtpb.ioNamePtr = sp->name;
  232.         sdtpb.ioDTRefNum = ServerDTRef;
  233.         sdtpb.ioDTBuffer = buf;
  234.         sdtpb.ioDTReqCount = sizeof(buf);
  235.         sdtpb.ioDirID = sp->parID;
  236.         Clue1 = "\pPBDTGetComment";
  237.         error = PBDTGetComment (&sdtpb, false);
  238.         if (error == afpItemNotFound || error == fnfErr || error == afpAccessDenied)
  239.         {
  240.             /*
  241.              * The AccessDenied clause above is for Novell, which requires
  242.              * "Write To File" access to read the comments???
  243.              */
  244.             sdtpb.ioDTActCount = 0;
  245.             error = 0;
  246.         }
  247.         if (error == 0)
  248.         {
  249.             /*
  250.              * If empty comment on server, don't cause write on client unless
  251.              * we have to.
  252.              */
  253.             if (sdtpb.ioDTActCount == 0)
  254.             {
  255.                 ZERO (cdtpb);
  256.                 cdtpb.ioNamePtr = cp->name;
  257.                 cdtpb.ioDTRefNum = ClientDTRef;
  258.                 cdtpb.ioDirID = cp->parID;
  259.                 cdtpb.ioDTBuffer = buf + sizeof(buf)/2;
  260.                 cdtpb.ioDTReqCount = sizeof(buf)/2;
  261.                 error = PBDTGetComment (&cdtpb, false);
  262.                 if (error == 0 && cdtpb.ioDTActCount == 0)
  263.                 {
  264.                     error = afpItemNotFound;    /* fake error to skip SetComment */
  265.                 }
  266.                 if (error == afpAccessDenied)
  267.                     error = afpItemNotFound;    /* also for Novell */
  268.             }
  269.             if (error == 0)
  270.             {
  271.                 ZERO (cdtpb);
  272.                 cdtpb.ioNamePtr = cp->name;
  273.                 cdtpb.ioDTRefNum = ClientDTRef;
  274.                 cdtpb.ioDirID = cp->parID;
  275.                 cdtpb.ioDTBuffer = buf;
  276.                 cdtpb.ioDTReqCount = sdtpb.ioDTActCount;
  277.                 if (Flags & PF_VERBOSE)
  278.                     notice (L_DTCOMM, cp->name, nil);
  279.                 if (!(Flags & PF_LISTONLY))
  280.                 {
  281.                     error = PBDTSetComment (&cdtpb, false);
  282.                     Clue1 = "\pPBDTSetComment";
  283.                     if (error == 0)
  284.                         modified = 1;
  285.                 }
  286.             }
  287.         }
  288.         if (error && error != afpItemNotFound && error != fnfErr)
  289.         {
  290.             ClueID = error;
  291.             warning (E_SYS, Clue0, Clue1, nil);
  292.         }
  293.     }
  294.     /*
  295.      * If the file does not have a bundle, we are done
  296.      */
  297.     if ((sp->in.f.finfo.fdFlags & fHasBundle) == 0)
  298.         goto out;
  299.     /*
  300.      * Copy any icons
  301.      */
  302.     if (ClientDTRef && ServerDTRef)
  303.     {
  304.         for (i = 1, error = 0; ; i++)
  305.         {
  306.             ZERO (sdtpb);
  307.             sdtpb.ioDTRefNum = ServerDTRef;
  308.             sdtpb.ioIndex = i;
  309.             sdtpb.ioFileCreator = sp->in.f.finfo.fdCreator;
  310.             sdtpb.ioIconType = 0;
  311.             error = PBDTGetIconInfo (&sdtpb, false);
  312.             if (error)
  313.             {
  314.                 if (error != afpItemNotFound && error != fnfErr)
  315.                 {
  316.                     ClueID = error;
  317.                     warning (E_SYS, Clue0, "\pPBDTGetIconInfo", nil);
  318.                 }
  319.                 break;
  320.             }
  321.             /*
  322.              * Check for valid icon types
  323.              */
  324.             for (j = 0; t = ii[j].itype; j++)
  325.                 if (t == sdtpb.ioIconType)
  326.                     break;
  327.             if (t == 0)
  328.                 continue;            /* ignore if not good icon type */
  329.             sdtpb.ioTagInfo = 0;
  330.             sdtpb.ioDTBuffer = buf;
  331.             sdtpb.ioDTReqCount = ii[j].isize;
  332.             error = PBDTGetIcon (&sdtpb, false);
  333.             if (error)
  334.             {
  335.                 ClueID = error;
  336.                 warning(E_SYS, Clue0, "\pPBDTGetIcon", nil);
  337.                 continue;
  338.             }
  339.             ZERO(cdtpb);
  340.             cdtpb.ioDTRefNum = ClientDTRef;
  341.             cdtpb.ioDTBuffer = buf;
  342.             cdtpb.ioDTReqCount = sdtpb.ioDTActCount;
  343.             cdtpb.ioIconType = sdtpb.ioIconType;
  344.             cdtpb.ioFileCreator = sdtpb.ioFileCreator;
  345.             cdtpb.ioFileType = sdtpb.ioFileType;
  346.             if (once++ == 0 && (Flags & PF_VERBOSE))
  347.                 notice (L_DTICON, cp->name, nil);
  348.             if (!(Flags & PF_LISTONLY))
  349.             {
  350.                 error = PBDTAddIcon (&cdtpb, false);
  351.                 if (error)
  352.                 {
  353.                     ClueID = error;
  354.                     warning(E_SYS, Clue0, "\pPBDTAddIcon", nil);
  355.                 }
  356.                 else
  357.                     modified = 1;
  358.             }
  359.         }
  360.     }
  361.     /*
  362.      * Last, update application location information
  363.      */
  364.     if (cp->in.f.finfo.fdType != 'APPL')
  365.         goto out;
  366.     if (ClientDTRef)
  367.     {
  368.         ZERO(cdtpb);
  369.         cdtpb.ioNamePtr = cp->name;
  370.         cdtpb.ioDTRefNum = ClientDTRef;
  371.         cdtpb.ioDirID = cp->parID;
  372.         cdtpb.ioFileCreator = cp->in.f.finfo.fdCreator;
  373.         if (!(Flags & PF_LISTONLY))
  374.         {
  375.             error = PBDTAddAPPL (&cdtpb, false);
  376.             if (error)
  377.             {
  378.                 ClueID = error;
  379.                 warning(E_SYS, Clue0, "\pPBDTAddAPPL", nil);
  380.             }
  381.             else
  382.                 modified = 1;
  383.         }
  384.         if (modified && (Flags & PF_VERBOSE))
  385.             notice (L_DTINFO, cp->name, nil);
  386. out:
  387.         if (modified)
  388.         {
  389.             ZERO(cdtpb);
  390.             cdtpb.ioDTRefNum = ClientDTRef;
  391.             error = PBDTFlush(&cdtpb, false);
  392.             if (error)
  393.             {
  394.                 ClueID = error;
  395.                 warning(E_SYS, Clue0, "\pPBDTFlush", nil);
  396.             }
  397.         }
  398.         return;
  399.     }
  400.     /*
  401.      * We get here if there is no client desktop database and so we
  402.      * need to update the Desktop file ourselves
  403.      */
  404.     modify_dtfile (cp, true);
  405. }
  406.  
  407.  
  408.  
  409. /*
  410.  *=========================================================================
  411.  * modify_dtfile (cp, flag) - modify entry in old style Finder Desktop file
  412.  * entry:    cp = ptr to cnode of file whose entry is to change
  413.  *            flag = true to add/update current information
  414.  *                 = false to delete current information
  415.  *=========================================================================
  416.  */
  417. void
  418. modify_dtfile (cnode_t *cp, Boolean flag)
  419. {
  420.     OSType            creator;            /* application signature */
  421.     int                doit;                /* set if decide need to munge it */
  422.     int                exact;                /* exact match flag */
  423.     api_t *            fp;                    /* pointer to ap info header */
  424.     Handle            hdl = 0;            /* handle to APPL resource */
  425.     SignedByte        hflags;                /* handle state */
  426.     Size            len;                /* temp byte length */
  427.     Size            newlen;                /* size of updated entry */
  428.     Size            origlen;            /* original resource size */
  429.     Size            offset;                /* offset of signature in APPL rsrc */
  430.     Ptr                p, ep;
  431.     StringPtr        s;                    /* temp string ptr */
  432.     struct {
  433.         api_t        api;
  434.         Str31        applname;
  435.     } newinfo;                            /* new application info */
  436.  
  437.     hdl = APPLh;
  438.     if (hdl == NULL)
  439.         return;                            /* if not available */
  440.     hflags = HGetState(hdl);
  441.     LoadResource (hdl);
  442.     if (ResError())
  443.         return;
  444.     HLock(hdl);
  445.     creator = cp->in.f.finfo.fdCreator;
  446.     doit = 1;                            /* assume work to do */
  447.     /*
  448.      * Now, search the resource for an entry with a matching creator
  449.      */
  450.     origlen = GetHandleSize (hdl);
  451.     for (p = *hdl, ep = p + origlen; p < ep; p += len)
  452.     {
  453.         fp = (api_t *)p;
  454.         s = (StringPtr) (fp+1);
  455.         len = sizeof(*fp) + (s[0] | 1) + 1;
  456.         if (fp->creator == creator)
  457.         {
  458.             /*
  459.              * Found existing entry.
  460.              * If updating, exit immediately if nothing different.
  461.              * If deleting, delete only on exact match
  462.              */
  463.             exact = fp->dirID == cp->parID
  464.              && EqualString (s, cp->name, false, true);
  465.             if (flag)
  466.             {
  467.                 if (exact)
  468.                     doit = 0;
  469.                 break;
  470.             }
  471.             else
  472.             {
  473.                 if (exact)
  474.                     break;
  475.             }
  476.         }
  477.     }
  478.     offset = p - *hdl;
  479.     if (offset >= origlen)                /* if no entry found */
  480.     {
  481.         len = 0;
  482.         if (!flag)                        /* if deleting and no entry, done */
  483.             doit = 0;
  484.     }
  485.     if (doit)
  486.     {
  487.         if (flag)
  488.         {
  489.             newinfo.api.creator = creator;
  490.             newinfo.api.dirID = cp->parID;
  491.             COPYPS(cp->name, newinfo.applname);
  492.             newlen = newinfo.applname[0];
  493.             if (newlen & 1)
  494.                 newinfo.applname[newlen+1] = 0;
  495.             newlen = sizeof (newinfo.api) + (newlen | 1) + 1;
  496.         }
  497.         else
  498.             newlen = 0;
  499.         /*
  500.          * Use Munger to replace/append/delete new info in resource
  501.          */
  502.         HUnlock(hdl);
  503.         if (Flags & PF_LISTONLY)
  504.             doit = 0;
  505.         if (doit)
  506.         {
  507.             len = Munger(hdl, offset, nil, len, (Ptr)&newinfo, newlen);
  508.             if (len < offset)
  509.             {
  510.                 ClueID = len;
  511.                 warning (E_SYS, "\pmodify_dtfile", "\pMunger", nil);
  512.             }
  513.         }
  514.         if (doit && (Flags & PF_VERBOSE))
  515.             notice (flag ? L_DTINFO : L_DTDEL, cp->name, nil);
  516.     }
  517.     HSetState (hdl, hflags);
  518.     if (doit)
  519.     {
  520.         ChangedResource (hdl);
  521.         WriteResource (hdl);
  522.     }
  523. }